#include "Acceptor.hpp"

namespace xww
{

Acceptor::Acceptor(unsigned short port,const string & ip)
:_addr(port, ip)
, _sock()
{

}

//这个函数的作用？
//它的目的是为了准备好Acceptor对象，使其可以接受连接请求
//通常在Acceptor对象创建后调用，设置一些必要的socket选项和状态
//例如设置地址复用、端口复用、绑定地址和端口等
//这样在调用accept()函数时，Acceptor就可以正常工作了
void Acceptor::ready()
{
    setReuseAddr(true);  //设置地址复用
    setReusePort(true);  //设置端口复用
    bind();              //绑定地址和端口
    listen();           //开始监听连接请求
}

//这个函数的作用是接受一个新的连接请求
//它会阻塞当前线程，直到有新的连接到来
//如果有新的连接到来，它会返回一个新的socket文件描述符
//如果没有新的连接到来，它会返回-1，并设置errno
//通常在Acceptor对象准备好后调用，等待客户端的连接请求
//返回的socket文件描述符可以用于与客户端进行通信
//如果没有新的连接到来，accept()函数会阻塞，直到有新的连接
int Acceptor::accept()
{
    struct sockaddr_in clientAddr;
    socklen_t addrLen = sizeof(clientAddr);
    int netfd = ::accept(_sock.fd(), (struct sockaddr*)&clientAddr, &addrLen);
    if (netfd < 0)
    {
        perror("accept");
        return -1; //返回-1表示没有新的连接
    }
    return netfd;//返回新的socket文件描述符

}

//设置地址复用选项
void Acceptor::setReuseAddr(bool on)
{
    int value = on;
    int ret = setsockopt(_sock.fd(), SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
    if(ret < 0)
    {
        perror("setsockopt");
    }

}

//设置端口复用选项
void Acceptor::setReusePort(bool on)
{
    int value = on;
    int ret = setsockopt(_sock.fd(), SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value));
    if(ret < 0)
    {
        perror("setsockopt");
    }

}
    
//绑定地址和端口到socket
//这个函数的作用是将InetAddress对象中的IP地址和端口号绑定到
//Acceptor对象的Socket上，使其可以监听来自该地址和端口的连接
//通常在ready()函数中调用，确保Acceptor对象可以接受连接请求
//如果绑定失败，会输出错误信息
//如果绑定成功，Acceptor对象就可以开始监听来自该地址和端口的连接请求
//注意：在调用bind()函数之前，必须确保Socket已经创建并且
void Acceptor::bind()
{
    int ret = ::bind(_sock.fd(),(struct sockaddr *)&_addr, sizeof(_addr));
    if(ret < 0)
    {   
        perror("bind");
    }
}

//开始监听连接请求
//这个函数的作用是开始监听来自客户端的连接请求
//它会将Acceptor对象的Socket设置为监听状态，准备接受连接请求
//通常在ready()函数中调用，确保Acceptor对象可以接受连接请求
//如果监听失败，会输出错误信息
//如果监听成功，Acceptor对象就可以开始接受来自客户端的连接请求
void Acceptor::listen()
{
    int ret = ::listen(_sock.fd(),10000);
    if(ret < 0)
    {
        perror("listen");
    }
}

}// end of namespace xww